#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
UDP服务器管理器
提供UDP服务器的启动、停止、客户端管理和消息发送功能
"""

import socket
import threading
from typing import Optional, Callable, Dict, Tuple, Any
from datetime import datetime

from utils.server.data_parse import is_modbus_data, parse_modbus_rtu


class UdpServerManager:
    """UDP服务器管理类"""
    
    def __init__(self, message_callback: Optional[Callable] = None):
        """
        初始化UDP服务器管理器
        
        Args:
            message_callback: 消息回调函数，用于向GUI发送日志消息
                             函数签名: callback(message: str, level: str = "INFO", msg_type: str = "normal")
                             msg_type可以是: "normal", "send", "receive", "error"
        """
        self.server_socket = None
        self.running = False
        self.client_addresses = set()  # 存储已知的客户端地址
        self.clients_lock = threading.Lock()
        
        # 回调函数
        self.message_callback = message_callback or self._default_callback
        
    def _default_callback(self, message: str, level: str = "INFO", msg_type: str = "normal"):
        """默认回调函数，打印到控制台"""
        timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        print(f"[{timestamp}] {level}: {message}")
    
    def start_server(self, host: str = "0.0.0.0", port: int = 9020) -> bool:
        """
        启动UDP服务器
        
        Args:
            host: 监听IP地址
            port: 监听端口
            
        Returns:
            bool: 启动是否成功
        """
        try:
            if self.server_socket:
                self.stop_server()
            
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind((host, port))
            
            self.running = True
            self.message_callback(f"UDP服务器已启动，监听 {host}:{port}")
            
            # 启动服务器接收数据的线程
            threading.Thread(target=self._receive_data, daemon=True).start()
            
            return True
            
        except Exception as e:
            self.message_callback(f"启动UDP服务器失败: {e}", "ERROR", "error")
            return False
    
    def stop_server(self):
        """停止UDP服务器"""
        try:
            self.running = False
            
            if self.server_socket:
                self.server_socket.close()
                self.server_socket = None
            
            with self.clients_lock:
                self.client_addresses.clear()
            
            self.message_callback("UDP服务器已停止")
            
        except Exception as e:
            self.message_callback(f"停止UDP服务器错误: {e}", "ERROR", "error")
    
    def get_client_count(self) -> int:
        """获取客户端数量"""
        with self.clients_lock:
            return len(self.client_addresses)
    
    def get_client_list(self) -> list:
        """获取客户端地址列表"""
        with self.clients_lock:
            return list(self.client_addresses)
    
    def _receive_data(self):
        """接收UDP数据的线程"""
        while self.running and self.server_socket:
            try:
                data, client_address = self.server_socket.recvfrom(1024)
                
                # 记录客户端地址
                with self.clients_lock:
                    if client_address not in self.client_addresses:
                        self.client_addresses.add(client_address)
                        self.message_callback(f"🔗 新UDP客户端 {client_address} [总客户端数: {len(self.client_addresses)}]")
                
                self.message_callback(f"📨 收到来自 {client_address} 的UDP数据:")
                
                # 判断是否为Modbus数据
                if is_modbus_data(data):
                    self.message_callback("🔍 检测到Modbus RTU协议数据", "INFO", "receive")
                    # 解析Modbus数据
                    parsed_result = parse_modbus_rtu(data)
                    self._log_modbus_data(data, parsed_result, client_address)
                else:
                    self.message_callback("📄 检测到非Modbus数据", "INFO", "receive")
                    self._log_raw_data(data, client_address)
                
            except Exception as e:
                if self.running:
                    self.message_callback(f"UDP接收数据错误: {e}", "ERROR", "error")
                break
    
    def _log_modbus_data(self, data: bytes, parsed_result: dict, client_address: tuple):
        """记录Modbus数据"""
        self.message_callback("┌─ Modbus UDP数据解析 ─────────────────", "INFO", "receive")
        self.message_callback(f"│ 客户端: {client_address}", "INFO", "receive")
        self.message_callback(f"│ 原始数据: {data.hex().upper()}", "INFO", "receive")
        self.message_callback(f"│ 数据长度: {len(data)} 字节", "INFO", "receive")
        
        if "error" in parsed_result:
            self.message_callback(f"│ ❌ 解析失败: {parsed_result['error']}", "ERROR", "receive")
        else:
            self.message_callback(f"│ 设备地址: {parsed_result['slave_id']}", "INFO", "receive")
            self.message_callback(f"│ 功能码: {parsed_result['function_code']} ({parsed_result['function']})", "INFO", "receive")
            self.message_callback(f"│ CRC校验: {'✅ 正确' if parsed_result['crc_valid'] else '❌ 错误'}", "INFO", "receive")
            
            # 显示具体数据
            if "registers" in parsed_result:
                self.message_callback(f"│ 寄存器数量: {len(parsed_result['registers'])}", "INFO", "receive")
                for i, reg_val in enumerate(parsed_result['registers']):
                    self.message_callback(f"│   寄存器{i}: {reg_val}", "INFO", "receive")
        
        self.message_callback("└─────────────────────────────────────", "INFO", "receive")
    
    def _log_raw_data(self, data: bytes, client_address: tuple):
        """记录原始数据"""
        self.message_callback("┌─ UDP原始数据 ────────────────────────", "INFO", "receive")
        self.message_callback(f"│ 客户端: {client_address}", "INFO", "receive")
        self.message_callback(f"│ 原始数据: {data.hex().upper()}", "INFO", "receive")
        self.message_callback(f"│ 数据长度: {len(data)} 字节", "INFO", "receive")
        
        # 尝试解码为文本
        try:
            text = data.decode('utf-8')
            if text.isprintable():
                self.message_callback(f"│ UTF-8文本: {text}", "INFO", "receive")
        except UnicodeDecodeError:
            self.message_callback("│ 无法解码为UTF-8文本", "INFO", "receive")
        
        self.message_callback("└─────────────────────────────────────", "INFO", "receive")
    
    def send_to_client(self, client_address: tuple, data: bytes) -> bool:
        """
        向指定客户端发送数据
        
        Args:
            client_address: 客户端地址 (ip, port)
            data: 要发送的数据
            
        Returns:
            bool: 发送是否成功
        """
        try:
            if not self.server_socket or not self.running:
                self.message_callback("UDP服务器未启动", "ERROR", "error")
                return False
            
            self.server_socket.sendto(data, client_address)
            self.message_callback(f"✅ 数据已发送到UDP客户端 {client_address}", "INFO", "send")
            self.message_callback(f"📤 发送数据: {data.hex().upper()}", "INFO", "send")
            
            return True
            
        except Exception as e:
            self.message_callback(f"向UDP客户端 {client_address} 发送数据失败: {e}", "ERROR", "error")
            return False
    
    def broadcast_to_all(self, data: bytes) -> bool:
        """
        向所有已知客户端广播数据
        
        Args:
            data: 要广播的数据
            
        Returns:
            bool: 广播是否成功
        """
        try:
            if not self.server_socket or not self.running:
                self.message_callback("UDP服务器未启动", "ERROR", "error")
                return False
            
            with self.clients_lock:
                if not self.client_addresses:
                    self.message_callback("没有已知的UDP客户端", "WARNING", "normal")
                    return False
                
                success_count = 0
                for client_address in self.client_addresses.copy():
                    try:
                        self.server_socket.sendto(data, client_address)
                        success_count += 1
                        self.message_callback(f"✅ 数据已广播到UDP客户端 {client_address}", "INFO", "send")
                    except Exception as e:
                        self.message_callback(f"向UDP客户端 {client_address} 广播失败: {e}", "ERROR", "error")
                        # 移除无效的客户端地址
                        self.client_addresses.discard(client_address)
                
                self.message_callback(f"📤 广播数据: {data.hex().upper()}", "INFO", "send")
                self.message_callback(f"📊 广播完成: {success_count}/{len(self.client_addresses)} 客户端", "INFO", "send")
                
                return success_count > 0
            
        except Exception as e:
            self.message_callback(f"UDP广播失败: {e}", "ERROR", "error")
            return False
    
    def parse_data_input(self, data_input: str) -> tuple:
        """
        解析输入的数据，支持文本和十六进制格式
        
        Args:
            data_input: 输入的数据字符串
            
        Returns:
            tuple: (byte_data, data_type, original_data)
        """
        if data_input.startswith('text:'):
            # 文本数据
            text_data = data_input[5:]  # 去掉 'text:' 前缀
            return text_data.encode('utf-8'), 'text', text_data
        else:
            # 尝试解析为十六进制数据
            try:
                hex_string = data_input.replace(' ', '').replace('-', '').replace(':', '')
                if len(hex_string) % 2 != 0:
                    hex_string = '0' + hex_string
                byte_data = bytes.fromhex(hex_string)
                return byte_data, 'hex', data_input
            except ValueError:
                # 如果不是有效的十六进制，当作文本处理
                return data_input.encode('utf-8'), 'text', data_input
